﻿using Dto;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Model;
using System.Text.Json;

namespace Dlpad.Services
{
    public class DictTypeService : IDictTypeService
    {
        private readonly ApplicationDbContext _context;
        private readonly IDistributedCache _cache;
        private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(30); //30分钟

        public DictTypeService(ApplicationDbContext context, IDistributedCache cache)
        {
            _context = context;
            _cache = cache;
        }

        public async Task<PagedResultDto<DictTypeResponseDto>> GetDictTypesAsync(DictTypeQueryDto query)
        {
            // 生成缓存键（基于查询参数） 动态缓存键
            var cacheKey = $"Dlpad_dict_types_paged_{query.PageNumber}_{query.PageSize}_{query.DictName}_{query.DictType}_{query.Status}";
            Console.WriteLine($"[DICT-TYPE-PAGED-CACHE] 使用缓存键: {cacheKey}");

            // 尝试从缓存获取
            string cachedData = null;
            try
            {
                cachedData = await _cache.GetStringAsync(cacheKey);//从缓存系统中异步读取字符串类型的数据
            }
            catch (Exception ex) when (ex.Message.Contains("WRONGTYPE"))
            {
                Console.WriteLine($"[CACHE-IGNORE] 忽略 hash 类型缓存: {cacheKey}");
                cachedData = null;
            }

            if (!string.IsNullOrEmpty(cachedData)) //缓存命中 即缓存不为空
            {
                Console.WriteLine($"[DICT-TYPE-PAGED-CACHE] 缓存命中: {cacheKey}");
                try
                {
                    return JsonSerializer.Deserialize<PagedResultDto<DictTypeResponseDto>>(cachedData);
                }
                catch (JsonException)
                {
                    Console.WriteLine($"[DICT-TYPE-PAGED-CACHE] 缓存数据反序列化失败");
                    await _cache.RemoveAsync(cacheKey);
                }
            }

            Console.WriteLine($"[DICT-TYPE-PAGED-CACHE] 缓存未命中，查询数据库");

            var queryable = _context.SysDictTypes.AsQueryable();

            // 构建查询条件
            if (!string.IsNullOrWhiteSpace(query.DictName))
            {
                queryable = queryable.Where(x => x.DictName.Contains(query.DictName));
            }

            if (!string.IsNullOrWhiteSpace(query.DictType))
            {
                queryable = queryable.Where(x => x.DictType.Contains(query.DictType));
            }

            if (!string.IsNullOrWhiteSpace(query.Status))
            {
                queryable = queryable.Where(x => x.Status == query.Status);
            }

            if (query.StartTime.HasValue)
            {
                queryable = queryable.Where(x => x.CreateTime >= query.StartTime.Value);
            }

            if (query.EndTime.HasValue)
            {
                var endTime = query.EndTime.Value.AddDays(1);
                queryable = queryable.Where(x => x.CreateTime < endTime);
            }

            // 获取总数
            var totalCount = await queryable.CountAsync();

            // 分页查询
            var items = await queryable
                .OrderByDescending(x => x.CreateTime)
                .Skip((query.PageNumber - 1) * query.PageSize)
                .Take(query.PageSize)
                .Select(x => new DictTypeResponseDto
                {
                    DictId = x.DictId,
                    DictName = x.DictName,
                    DictType = x.DictType,
                    Status = x.Status,
                    Remark = x.Remark,
                    CreateTime = x.CreateTime
                })
                .ToListAsync();

            var result = new PagedResultDto<DictTypeResponseDto>
            {
                TotalCount = totalCount,
                Items = items,
                PageNumber = query.PageNumber,
                PageSize = query.PageSize
            };

            // 将结果存入缓存（缓存时间较短，因为分页查询变化频繁）
            try
            {
                var cacheOptions = new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5) // 5分钟
                };

                await _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(result), cacheOptions);
                Console.WriteLine($"[DICT-TYPE-PAGED-CACHE] 分页缓存写入成功: {cacheKey}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[DICT-TYPE-PAGED-CACHE] 分页缓存写入失败: {ex.Message}");
            }

            return result;
        }

        public async Task<SysDictType?> GetDictTypeByIdAsync(long id)
        {
            //尝试从缓存获取
            var cacheKey = $"Dlpad_dict_type_{id}";

            string cachedData = null;
            try
            {
                cachedData = await _cache.GetStringAsync(cacheKey); //缓存命中后的反序列化操作 将JSON字符串还原为强类型对象
            }
            catch (Exception ex) when (ex.Message.Contains("WRONGTYPE"))
            {
                // 忽略 hash 类型缓存错误
                Console.WriteLine($"[CACHE-IGNORE] 忽略 hash 类型缓存: {cacheKey}");
                cachedData = null;
            }

            if (!string.IsNullOrEmpty(cachedData))
            {
                //缓存命中，直接返回
                return JsonSerializer.Deserialize<SysDictType>(cachedData);
            }

            //若缓存未命中，从数据库中获取数据
            var dictType = await _context.SysDictTypes.FindAsync(id);
            if (dictType != null)
            {
                //将数据缓存起来
                var cacheOptions = new DistributedCacheEntryOptions //决定了  "缓存何时过期、如何过期"
                {
                    AbsoluteExpirationRelativeToNow = _cacheExpiration  
                    //优先级：AbsoluteExpiration > AbsoluteExpirationRelativeToNow > SlidingExpiration
                };

                try
                {
                    await _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(dictType), cacheOptions);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[CACHE-ERROR] 设置字典类型缓存失败: {ex.Message}");
                }
            }
            return dictType;
        }

        public async Task<bool> CreateDictTypeAsync(SysDictType dictType)
        {
            try
            {
                _context.SysDictTypes.Add(dictType);
                await _context.SaveChangesAsync();

                //清除相关缓存并立即重新填充
                await ClearDictTypeCache();

                // 立即重新加载到缓存
                await GetAllDictTypesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> UpdateDictTypeAsync(SysDictType dictType)
        {
            try
            {
                Console.WriteLine($"=== 使用Attach方式更新 ===");
                // 获取旧的字典类型信息（用于清理缓存）
                var oldDictType = await _context.SysDictTypes
                    .AsNoTracking()
                    .FirstOrDefaultAsync(x => x.DictId == dictType.DictId);

                // 先检查实体是否存在
                var exists = await _context.SysDictTypes.AnyAsync(x => x.DictId == dictType.DictId);
                if (!exists)
                {
                    Console.WriteLine($"实体不存在: ID={dictType.DictId}");
                    return false;
                }

                // 使用 Attach 和状态修改  1. 先落库（只改 DB）
                _context.SysDictTypes.Attach(dictType);
                _context.Entry(dictType).State = EntityState.Modified;

                // 排除创建时间和创建者不被更新
                _context.Entry(dictType).Property(x => x.CreateTime).IsModified = false;
                _context.Entry(dictType).Property(x => x.CreateBy).IsModified = false;

                Console.WriteLine($"开始保存到数据库...");
                var saveResult = await _context.SaveChangesAsync();
                Console.WriteLine($"数据库保存成功: {saveResult} 行受影响");

                //清除缓存
                await ClearDictTypeCache(); //列表
                await _cache.RemoveAsync($"dict_type_{dictType.DictId}");
                // 2. 写完库立刻删缓存（写时失效） 单条
               //下一次 GetDictTypeByIdAsync 或 GetAllDictTypesAsync 就会重新走「读未命中」分支，自然加载最新数据并回填缓存

                //如果字典类型改变，清除旧的字典数据缓存
                if (oldDictType != null && oldDictType.DictType != dictType.DictType)
                {
                    await _cache.RemoveAsync($"Dlpad_dict_data_{oldDictType.DictType}");
                }
                //清除新的字典数据缓存
                await _cache.RemoveAsync($"Dlpad_dict_data_{dictType.DictType}");
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Attach方式更新异常: {ex.Message}");
                return false;
            }
        }

        public async Task<bool> DeleteDictTypeAsync(long id)
        {
            try
            {
                var dictType = await _context.SysDictTypes.FindAsync(id);
                if (dictType != null)
                {
                    _context.SysDictTypes.Remove(dictType);
                    await _context.SaveChangesAsync();

                    //清除相关缓存
                    await ClearDictTypeCache();
                    //清除特定字段类型的缓存
                    await _cache.RemoveAsync($"Dlpad_dict_type_{dictType.DictId}");
                    //清除对应的字典数据缓存
                    await _cache.RemoveAsync($"Dlpad_dict_data_{dictType.DictType}");
                }
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"删除字典类型失败: {ex.Message}");
                return false;
            }
        }

        public async Task<bool> IsDictTypeUniqueAsync(string dictType, long? excludeId = null)
        {
            try
            {
                Console.WriteLine($"检查唯一性 - DictType: {dictType}, 排除ID: {excludeId}");

                var query = _context.SysDictTypes.Where(x => x.DictType == dictType);

                if (excludeId.HasValue)
                {
                    query = query.Where(x => x.DictId != excludeId.Value);
                }

                var exists = await query.AnyAsync();
                Console.WriteLine($"唯一性检查结果: {!exists} (存在={exists})");

                return !exists;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"唯一性检查异常: {ex.Message}");
                throw;
            }
        }

        public async Task<List<DictTypeResponseDto>> GetAllDictTypesAsync()
        {
            // 尝试从缓存获取
            var cacheKey = "Dlpad_all_dict_types";
            Console.WriteLine($"[DICT-TYPE-CACHE] 使用缓存键: {cacheKey}");

            // 使用 GetStringAsync 获取缓存
            string cachedData = null;
            try
            {
                cachedData = await _cache.GetStringAsync(cacheKey);
                Console.WriteLine($"[DICT-TYPE-CACHE] 缓存读取结果: {(string.IsNullOrEmpty(cachedData) ? "空" : "有数据")}");
            }
            catch (Exception ex) when (ex.Message.Contains("WRONGTYPE"))
            {
                // 忽略 hash 类型缓存错误
                Console.WriteLine($"[CACHE-IGNORE] 忽略 hash 类型缓存: {cacheKey}");
                cachedData = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[CACHE-ERROR] 读取缓存异常: {ex.Message}");
                cachedData = null;
            }

            if (!string.IsNullOrEmpty(cachedData))
            {
                //缓存命中，直接返回
                Console.WriteLine($"[DICT-TYPE-CACHE] 缓存命中: {cacheKey}");
                try
                {
                    var result = JsonSerializer.Deserialize<List<DictTypeResponseDto>>(cachedData);
                    Console.WriteLine($"[DICT-TYPE-CACHE] 返回缓存数据: {result?.Count ?? 0} 条");
                    return result ?? new List<DictTypeResponseDto>();
                }
                catch (JsonException ex)
                {
                    Console.WriteLine($"[DICT-TYPE-CACHE] 缓存数据反序列化失败: {ex.Message}");
                    await _cache.RemoveAsync(cacheKey);
                }
            }

            Console.WriteLine($"[DICT-TYPE-CACHE] 缓存未命中，查询数据库");

            //若缓存未命中，从数据库中获取数据
            var dictTypes = await _context.SysDictTypes
                .Where(x => x.Status == "0")//只获取正常状态的
                .OrderBy(x => x.DictName)
                .Select(x => new DictTypeResponseDto
                {
                    DictId = x.DictId,
                    DictName = x.DictName,
                    DictType = x.DictType,
                    Status = x.Status,
                    Remark = x.Remark,
                    CreateTime = x.CreateTime
                })
                .ToListAsync();

            // 将数据存入缓存 - 加强错误处理
            if (dictTypes.Any())
            {
                try
                {
                    var cacheOptions = new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) // 改为1小时
                    };

                    var jsonData = JsonSerializer.Serialize(dictTypes);
                    Console.WriteLine($"[DICT-TYPE-CACHE] 准备写入缓存，JSON长度: {jsonData.Length}");

                    // 写入前先删除可能存在的旧缓存
                    await _cache.RemoveAsync(cacheKey);

                    // 写入缓存
                    await _cache.SetStringAsync(cacheKey, jsonData, cacheOptions);
                    Console.WriteLine($"[DICT-TYPE-CACHE] 缓存写入成功: {cacheKey}");

                    // 立即验证写入是否成功
                    await Task.Delay(100); // 短暂延迟
                    var verifyData = await _cache.GetStringAsync(cacheKey);
                    if (!string.IsNullOrEmpty(verifyData))
                    {
                        Console.WriteLine($"[CACHE-VERIFY] 验证成功 - 缓存已持久化");
                    }
                    else
                    {
                        Console.WriteLine($"[CACHE-VERIFY] 验证失败 - 缓存写入后立即丢失");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[DICT-TYPE-CACHE] 缓存写入失败: {ex.Message}");
                    Console.WriteLine($"[DICT-TYPE-CACHE] 异常类型: {ex.GetType()}");
                    Console.WriteLine($"[DICT-TYPE-CACHE] 堆栈跟踪: {ex.StackTrace}");
                }
            }

            return dictTypes;
        }

        /// <summary>
        /// 从数据库获取所有字典类型（不经过缓存）
        /// </summary>
        public async Task<List<DictTypeResponseDto>> GetAllDictTypesFromDbAsync()
        {
            return await _context.SysDictTypes
                .Where(x => x.Status == "0")//只获取正常状态的
                .OrderBy(x => x.DictName)
                .Select(x => new DictTypeResponseDto
                {
                    DictId = x.DictId,
                    DictName = x.DictName,
                    DictType = x.DictType,
                    Status = x.Status,
                    Remark = x.Remark,
                    CreateTime = x.CreateTime
                })
                .ToListAsync();
        }

        /// <summary>
        /// 清除字典类型相关的缓存
        /// </summary>
        private async Task ClearDictTypeCache()
        {
            try
            {
                // 清除所有字典类型列表缓存
                await _cache.RemoveAsync("Dlpad_all_dict_types");

                // 可以根据需要清除其他相关缓存
                // 例如：await _cache.RemoveAsync("dict_types_paged_*");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"清除缓存失败: {ex.Message}");
            }
        }
    }
}